package com.jeeplus.modules.api.utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.google.common.collect.Maps;
import com.jeeplus.common.config.Global;

public class AlipayUtils {
	private static Logger logger = LoggerFactory.getLogger(AlipayUtils.class);

	private static final String APP_ID = "2019102468560598"; // 正式版
	// 应用私钥 正式
	private static final String APP_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDn8Gdgb8DLnMPtrehZY+BZEgzPZf3GQ1nQ+prNO83Neh8BknFfH53fAuU+Bgkk/xstGdKJWW2ergNAq1Q1kfuX4c8CFVFb8LJ8NDLqdfGPY2BKT+q50D5G9r56rsP3iBdw4JDSCwLlEz80gd5DUKHxTuJjam0ZttorLDvQrKHbwqDqr3Jr1RvoEQM5t1QWwlbsgNfip8C4zBQBwkjQagMUg5DLNrX8SRZYoNgt2vBl7GdHncp++xUh3sdcCL/dG+hHMJNkE+FTWGO9M5qKFWprpNutP7CKONbHEB8oNMWWUq5SqKKN1iJYQUGT/G63z5oDSEA6lB8kD85tcZ4/FIjHAgMBAAECggEAeQOzzFtCinoGuDIussUrvw1t5aBfYlytth2rOz3iyTzYhKd1w53pbvxBw7S+fLEl6sg4UzV3vn0ocUtzKmg6jypgKcQZqRDS738EudRD7v54tQ0xeTWv6LLA+53H3ZUCNgDVTuIz5nW+WpUP9KtTc2YnNJvIxMvk1PXFV8Fayh+p8dPbMyiTqOWqipaJD4di2o1uZHT8db3KmV0Wb0h/pULDX9KZ7kttXjbenvFqTgwQaUje72DS8zx1h2P/ZAR1baOyVcqYRLNfcdmdlr+VoExnNOAOZ3V+38rEvIYqW7yYOvVLrbqZXvunil2xuDbJbempJg5t8cRge4twITfocQKBgQD+1hCbKDfGKNncWeG7HWmqWHYwVH9COFxiy7Wl7dYvSvXOAsUiBXzB1FMda4gui0ljb5XcyVjpgvuHfI0AiDZXfeEEUii7BPHVAhqMmmawZkq9rX8o8J2ZRHa//S2Sz7b/whOqdN4Ea8m8bqIvTyJdDH2DZlymMvxADMtfyI/sswKBgQDo/5HC7DOd4K+d8NneGwxSbIopKnCotMvdqJFzpClQjCE+dXJEw1q6xdNNBUEIzU7FdGNxul3rUxEfSsGbfDfNtlxr05PPNhn7iIZZcb9fzp/DGdswDeP2qVKtrcixXI85apU/tSO5476jyAOgQeglZ9kLUlNiAEHKx+BjWjulnQKBgCF4vHWksq60bukiZSPOmTJmrB9s+coY3Qmc+B7zPk636dFFS99MGTbcTI5wsVJruRf2cBiv2Z3SNnd1RI/tVDXpssR+hhsKazkvLY2KOjKxPN/tCea2s/yNoYtWFcZSwhaVxz98Wiz6e2TkoyjTnA/ctB+uMj0iNT+0boIGNeFBAoGBAMGgucJyRob6VRd9M6FHexr4RmzlbxBUh2MilhWzI/5jJbFhKuAINNsoUWwdZKlq7P5ctdOqXCiXNJB7sJ+FQF69INseziQSQs9s6rFkPPTiopQhZazurjarCiF5XWI/mGrPr05tO05c/G3hZ1oDy2digNXOyaqUqhhZuJj4QL9lAoGAcHmtmCZWmhlyA+IMJCqJPWPISSbZk30K1lYfMOCZjhFkc568Ly4nYPg8LyE3YRW8+SeMBYyVPIoi5phuxvhoXN5ODvJgfBa56OjQ0NlHUClPp9kBh426QhUqceNrXEc0F3kqwjK29vb1p0V05BQdaiTAmjG1inJ6pqM9tst0Qzs=";
	public static final String CHARSET = "UTF-8";
	// 支付宝公钥 正式
	private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApGiTTiK2uz4G8hZEGVfCGWqbMNC1tvT4Rf9vzmpDmCNElsAuOJunT7lCShPVjH9vXPDFa/iUf497Jzhup+1c4QaIvInE0WH3VwI+Ql3bj4uRYIYoyUJkL3Bh98MFVcFZWRlUnGdJ0k+DqXo9RvKr1FLkvtgDPzrVmRUhn5NpMXB9H2V/xXYlX8u+7erD5ona+Lm+0v4/9xRMQnM3/G+AZWQUwgeRsr2PsYXUJJbLzYpIVS6+LDHF/TElrHz+W7fjUlfgu2bDUDuejIBoEoxzqSceAsKt0oCkZbKLI9xYsf6Mk8YxZbHhk80xzGr0JTBKk+qVbXsLhs/NadgfyhYtsQIDAQAB";
	// 支付宝公匙 正式
	// private static final String ALIPAY_KEY =
	// "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApGiTTiK2uz4G8hZEGVfCGWqbMNC1tvT4Rf9vzmpDmCNElsAuOJunT7lCShPVjH9vXPDFa/iUf497Jzhup+1c4QaIvInE0WH3VwI+Ql3bj4uRYIYoyUJkL3Bh98MFVcFZWRlUnGdJ0k+DqXo9RvKr1FLkvtgDPzrVmRUhn5NpMXB9H2V/xXYlX8u+7erD5ona+Lm+0v4/9xRMQnM3/G+AZWQUwgeRsr2PsYXUJJbLzYpIVS6+LDHF/TElrHz+W7fjUlfgu2bDUDuejIBoEoxzqSceAsKt0oCkZbKLI9xYsf6Mk8YxZbHhk80xzGr0JTBKk+qVbXsLhs/NadgfyhYtsQIDAQAB";//支付宝共匙

	private static final String SIGNTYPE = "RSA2";
	private static final String NOTIFYURL = Global.getConfig("filePath") + "/webhook/aliPayNotify";// "商户外网可以访问的异步地址"
																									// 回调地址不可以带参数
	private static final String RETURNURL = Global.getConfig("filePath") + "/";// 成功后返回的页面地址
	private static final String TIMEOUT_EXPRESS = "30m";
	private static final String URL = "https://openapi.alipay.com/gateway.do"; // 正式
	public static final String app = "1";
	public static final String h5 = "2";
	public static final String pc = "3";

	/**
	 * 根据授权码获取支付宝用户信息
	 * 
	 * @param code
	 * @return
	 */
	public static Map<String, String> getAccessTokenAndUserId(String code) {
		Map<String, String> map = Maps.newHashMap();
		map.put("result", "1");
		try {
			AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, SIGNTYPE);
			// 使用auth_code获取access_token与user_id
			AlipaySystemOauthTokenRequest requests = new AlipaySystemOauthTokenRequest();
			requests.setCode(code);
			requests.setGrantType("authorization_code");
			AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(requests);
			if (oauthTokenResponse.isSuccess()) {
				AlipayUserInfoShareRequest requestUser = new AlipayUserInfoShareRequest();
				AlipayUserInfoShareResponse userinfoShareResponse = alipayClient.execute(requestUser, oauthTokenResponse.getAccessToken());
				if (userinfoShareResponse != null) {
					String userId = userinfoShareResponse.getUserId();// 用户ID
					String nickName = userinfoShareResponse.getNickName();// 用户昵称
					String avatar = userinfoShareResponse.getAvatar();// 用户头像
					map.put("userId", userId);
					map.put("nickName", nickName);
					map.put("avatar", avatar);
					map.put("result", "0");
				}
			}
		} catch (Exception e) {
			map.put("resultNote", "授权失败");
			logger.error("支付宝获取授权信息失败： " + e.getMessage());
		}
		return map;
	}

	/**
	 * 创建支付宝订单
	 * 
	 * @param subject
	 *            订单标题
	 * @param body
	 *            商品描述
	 * @param price
	 *            价格
	 * @param orderid
	 *            支付宝订单编号
	 * @param type
	 *            1-APP 2-H5
	 * @return
	 */
	public static String createOrder(String subject, String body, String price, String orderid, String type) {
		return createOrder(subject, body, price, orderid, type, RETURNURL);
	}

	/**
	 * 创建支付宝订单
	 * 
	 * @param subject
	 *            订单标题
	 * @param body
	 *            商品描述
	 * @param price
	 *            价格
	 * @param orderid
	 *            支付宝订单编号
	 * @param type
	 *            1-APP 2-H5
	 * @param returnUrl
	 *            返回页面路径
	 * @return
	 */
	public static String createOrder(String subject, String body, String price, String orderid, String type, String returnUrl) {
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, SIGNTYPE);
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayRequest request = new AlipayTradeAppPayRequest();
		String productCode = "QUICK_MSECURITY_PAY";
		if (h5.equals(type)) {
			request = new AlipayTradeWapPayRequest();
		} else if (pc.equals(type)) {
			request = new AlipayTradePagePayRequest();
			productCode = "FAST_INSTANT_TRADE_PAY";
		}
		// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody(body);
		model.setSubject(subject);
		model.setOutTradeNo(orderid);// 更换为自己的订单编号
		model.setTimeoutExpress(TIMEOUT_EXPRESS);
		model.setTotalAmount(price);// 订单价格
		model.setProductCode(productCode);
		request.setBizModel(model);
		request.setNotifyUrl(NOTIFYURL);//
		request.setReturnUrl(StringUtils.isNotBlank(returnUrl) ? returnUrl : RETURNURL);
		String orderStr = "";
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			if (h5.equals(type) || pc.equals(type)) {
				orderStr = alipayClient.pageExecute(request).getBody();
			} else {
				orderStr = alipayClient.sdkExecute(request).getBody();
			}
			logger.debug("支付宝返回数据：" + orderStr);
		} catch (AlipayApiException e) {
			logger.error("生成支付宝订单异常:" + e.getMessage());
			throw new RuntimeException("生成支付宝订单异常:" + e.getMessage());
		}
		return orderStr;
	}

	/**
	 * 退款
	 * 
	 * @param out_trade_no
	 *            订单号 订单支付时传入的商户订单号
	 * @param refund_amount
	 *            退款金额 该金额不能大于订单金额,单位为元，支持两位小数
	 * @return
	 */
	public static String refund(String out_trade_no, String refund_amount,String out_request_no) {
		AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, SIGNTYPE);
		AlipayTradeRefundRequest requests = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel bizModel = new AlipayTradeRefundModel();
		bizModel.setOutTradeNo(out_trade_no);
		if("1".equals(out_request_no)){
			bizModel.setOutRequestNo(out_trade_no);// 标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
		}
		// bizModel.setTradeNo(tradeNo);
		bizModel.setRefundAmount(refund_amount);

		requests.setBizModel(bizModel);

		AlipayTradeRefundResponse response = null;
		String result = "";
		try {
			response = alipayClient.execute(requests);
			result = response.getBody();
			logger.debug("支付宝退款结果：" + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 获取支付宝异步返回值
	 * 
	 * @param request
	 * @return
	 */
	public static JSONObject getReceiveMap(HttpServletRequest request) {
		// 获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		Map<String, String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = iter.next();
			String[] values = requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);

		}
		// Map<String,Object> result=new HashMap<>();
		JSONObject result = new JSONObject();
		result.putAll(params);
		result.put("signVerified", false);// 判断验签是否成功
		// 切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		// boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String
		// publicKey, String charset, String sign_type)
		try {
			logger.debug("------支付宝异步通知参数-------" + params.toString());
			boolean flag = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, SIGNTYPE);
			logger.debug("------支付宝异步签名认证-------" + flag);
			result.put("signVerified", flag);
		} catch (AlipayApiException e) {
			logger.error("支付宝异步回调核对信息失败:" + e.getMessage());
		}
		return result;
	}

}
